package com.springboot.file.util.easyexcel;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.springboot.file.exception.BusinessException;
import com.springboot.file.util.easyexcel.annotation.EasyExport;
import com.springboot.file.util.easyexcel.annotation.EasyImport;
import com.springboot.file.util.easyexcel.converter.CustomBigDecimalConverter;
import com.springboot.file.util.easyexcel.converter.CustomDateConverter;
import com.springboot.file.util.easyexcel.converter.CustomLocalDateConverter;
import com.springboot.file.util.easyexcel.converter.CustomLocalDateTimeConverter;
import com.springboot.file.util.easyexcel.converter.CustomNumberConverter;
import com.springboot.file.util.easyexcel.exception.ExcelValidationException;
import com.springboot.file.util.easyexcel.provider.ExportProvider;
import com.springboot.file.util.easyexcel.strategy.CustomCellStyleStrategy;
import com.springboot.file.util.easyexcel.strategy.CustomWidthStyleStrategy;
import com.springboot.file.util.easyexcel.strategy.HorizontalCellMergeStrategy;
import com.springboot.file.util.easyexcel.strategy.SingleRowHeaderStrategy;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.Objects;

/**
 * EasyExcel工具类，封装了常用的导入导出方法，并提供了注解和监听器的注册机制，可根据业务类型自动选择对应的监听器和导出提供者。
 *
 * @author liuc
 */
@Slf4j
@Component
public class EasyExcelUtil {
    /**
     * 存储业务类型注解和对应监听器的映射
     */
    private static final Map<String, ReadListener<?>> listenerMap = new HashMap<>();
    
    /**
     * 存储业务类型注解和对应导出提供者的映射
     */
    private static final Map<String, ExportProvider<?>> exportProviderMap = new HashMap<>();
    
    /**
     * 最大并发导入/导出任务数，避免同时启动过多导入导出
     */
    private static final int MAX_CONCURRENT_TASKS = 3;
    
    /**
     * 内存安全阈值: 当可用堆内存低于此百分比时，暂停新导入导出
     */
    private static final double MEMORY_SAFETY_THRESHOLD = 0.10; // 10%，更保守的内存阈值
    
    /**
     * 百分比格式化模式
     */
    private static final String PERCENT_FORMAT = "%.2f%%";
    
    /**
     * 默认每个sheet最大行数 减少到1万/sheet以降低内存使用
     */
    private static final int DEFAULT_MAX_ROWS_PER_SHEET = 10000; 
    
    /**
     * 批量写入数据的行数，分批写入以减少内存占用
     */
    private static final int BATCH_WRITE_SIZE = 300; // 减少批次大小，提高写入频率
    
    /**
     * 最大并发加载页数，控制异步任务数量，避免同时加载太多数据导致内存溢出
     */
    private static final int MAX_CONCURRENT_PAGES = 1; // 减少并发页面数，一次只加载一个page
    
    /**
     * Sheet前缀，用于日志和错误信息中
     */
    private static final String SHEET_PREFIX = "Sheet";
    
    /**
     * 并发导入/导出控制信号量
     */
    private final Semaphore taskSemaphore = new Semaphore(MAX_CONCURRENT_TASKS);
    
    /**
     * Spring 线程池
     */
    @Resource
    private ThreadPoolTaskExecutor executor;
    
    /**
     * 记录当前正在进行的任务数量
     */
    private final AtomicInteger taskCount = new AtomicInteger(0);
    
    /**
     * 内存管理器
     */
    private final MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();

    // 导出专用线程池，与一般任务分开处理，避免相互影响
    private ThreadPoolExecutor exportThreadPool;

    // Constants for parameter keys
    private static final String PARAM_SHEET_NO = "sheetNo";
    private static final String PARAM_START_RECORD = "startRecord";
    private static final String PARAM_END_RECORD = "endRecord";

    /**
     * 事务处理服务，用于确保事务生效
     */
    @Resource
    private ExcelTransactionService excelTransactionService;

    @PostConstruct
    private void initExportThreadPool() {
        // 创建导出专用线程池，核心线程数较小，最大线程数适中
        exportThreadPool = new ThreadPoolExecutor(
                2, // 核心线程
                4, // 最大线程
                60, // 空闲线程存活时间
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100), // 使用有界队列防止OOM
                new ExcelExportThreadFactory(), // 使用自定义命名的线程工厂
                new ThreadPoolExecutor.CallerRunsPolicy() // 队列满时，由调用线程执行任务
        );
        
        log.info("Excel导出专用线程池已初始化");
    }

    /**
     * Excel导出专用线程工厂
     */
    private static class ExcelExportThreadFactory implements ThreadFactory {
        private final AtomicInteger counter = new AtomicInteger(1);
        
        @Override
        public Thread newThread(Runnable r) {
            if (r == null) {
                throw new NullPointerException("Runnable cannot be null");
            }
            Thread thread = new Thread(r, "excel-export-thread-" + counter.getAndIncrement());
            thread.setDaemon(true); // 设置为守护线程
            return thread;
        }
    }

    @PreDestroy
    public void cleanupThreadPool() {
        if (exportThreadPool != null && !exportThreadPool.isShutdown()) {
            exportThreadPool.shutdown();
            try {
                if (!exportThreadPool.awaitTermination(10, TimeUnit.SECONDS)) {
                    exportThreadPool.shutdownNow();
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                exportThreadPool.shutdownNow();
            }
            log.info("Excel导出线程池已关闭");
        }
    }

    /**
     * 注册监听器
     * @param listener 数据监听器
     */
    public void registerListener(ReadListener<?> listener) {
        Annotation[] annotations = listener.getClass().getAnnotations();
        for (Annotation annotation : annotations) {
            if (annotation instanceof EasyImport easyImport) {
                String type = easyImport.value().getType();
                listenerMap.put(type, listener);
                log.info("已注册业务类型 [{}] 的监听器: {}", type, listener.getClass().getSimpleName());
            }
        }
    }
    
    /**
     * 注册导出提供者
     * @param provider 导出提供者
     */
    public void registerExportProvider(ExportProvider<?> provider) {
        Annotation[] annotations = provider.getClass().getAnnotations();
        for (Annotation annotation : annotations) {
            if (annotation instanceof EasyExport easyExport) {
                String type = easyExport.value().getType();
                exportProviderMap.put(type, provider);
                log.info("已注册业务类型 [{}] 的导出提供者: {}", type, provider.getClass().getSimpleName());
            }
        }
    }

    /**
     * 根据业务类型获取监听器
     * @param type 业务类型
     * @return 对应的监听器
     */
    @SuppressWarnings("unchecked")
    public <T> ReadListener<T> getListenerByType(String type) {
        return (ReadListener<T>) listenerMap.get(type);
    }
    
    /**
     * 根据业务类型获取导出提供者
     * @param type 业务类型
     * @return 对应的导出提供者
     */
    @SuppressWarnings("unchecked")
    public <T> ExportProvider<T> getExportProviderByType(String type) {
        return (ExportProvider<T>) exportProviderMap.get(type);
    }

    /**
     * 导入数据的方法
     * @param businessType 业务类型
     * @param file 上传的文件
     */
    public void importData(String businessType, MultipartFile file) {
        String fileName = file.getOriginalFilename();
        log.info("准备导入业务类型 [{}] 的文件: {}, 大小: {} bytes", businessType, fileName, file.getSize());
        
        // 检查内存状态
        if (isMemoryInsufficient()) {
            throw new BusinessException("系统内存不足，请稍后再试");
        }
        
        // 尝试获取导入许可
        boolean permitAcquired = false;
        try {
            // 尝试在5秒内获取许可
            permitAcquired = taskSemaphore.tryAcquire(5, TimeUnit.SECONDS);
            if (!permitAcquired) {
                throw new BusinessException("当前导入任务过多，请稍后再试");
            }
            
            // 记录任务计数
            taskCount.incrementAndGet();
            
            // 获取监听器
            ReadListener<?> listener = getListenerByType(businessType);
            if (listener == null) {
                throw new IllegalArgumentException("未找到对应业务类型注解的监听器: " + businessType);
            }
            
            // 获取实体类型
            Class<?> clazz = getEntityClass(listener);
            
            // 执行Excel导入
            processExcelFile(file, fileName, businessType, listener, clazz);
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("获取导入许可被中断", e);
            throw new BusinessException("导入操作被中断");
        } catch (ExcelValidationException e) {
            // 直接抛出Excel校验异常，不再包装
            log.error("Excel校验异常: {}", e.getMessage(), e);
            throw e;
        } finally {
            // 减少任务计数
            int remainingTasks = taskCount.decrementAndGet();
            log.info("导入任务完成，剩余任务数: {}", remainingTasks);
            
            // 释放导入许可
            if (permitAcquired) {
                taskSemaphore.release();
            }
        }
    }
    
    /**
     * 处理Excel文件导入
     * 
     * @param file 上传的Excel文件
     * @param fileName 文件名
     * @param businessType 业务类型
     * @param listener 数据监听器
     * @param clazz 实体类型
     * @throws BusinessException 业务异常
     */
    private void processExcelFile(MultipartFile file, String fileName, String businessType, 
                                 ReadListener<?> listener, Class<?> clazz) throws BusinessException {
        try (
            InputStream inputStream = new BufferedInputStream(file.getInputStream());
            ExcelReader excelReader = EasyExcelFactory.read(inputStream)
                    .registerConverter(new CustomBigDecimalConverter())
                    .registerConverter(new CustomLocalDateConverter())
                    .registerConverter(new CustomLocalDateTimeConverter())
                    .registerConverter(new CustomDateConverter())
                    .registerConverter(new CustomNumberConverter())
                    .build()
        ) {
            // 获取Excel文件中的sheet数量
            List<ReadSheet> readSheets = excelReader.excelExecutor().sheetList();

            if (readSheets == null || readSheets.isEmpty()) {
                log.warn("文件 [{}] 没有包含任何sheet", fileName);
                return;
            }

            log.info("文件 [{}] 包含 {} 个sheet", fileName, readSheets.size());

            // 读取所有sheet
            for (int i = 0; i < readSheets.size(); i++) {
                // 为每个sheet创建读取配置
                ReadSheet readSheet = EasyExcelFactory.readSheet(i)
                        .head(clazz)
                        .registerConverter(new CustomBigDecimalConverter())
                        .registerConverter(new CustomLocalDateConverter())
                        .registerConverter(new CustomLocalDateTimeConverter())
                        .registerConverter(new CustomDateConverter())
                        .registerConverter(new CustomNumberConverter())
                        .registerReadListener(listener)
                        .build();

                log.info("开始读取sheet [{}]", i);
                excelReader.read(readSheet);
                log.info("sheet [{}] 读取完成", i);
            }

            log.info("文件 [{}] 的业务类型 [{}] 全部sheet导入完成，共处理 {} 个sheet",
                    fileName, businessType, readSheets.size());
        } catch (IOException e) {
            log.error("导入数据IO异常：", e);
            throw new BusinessException("导入数据异常：" + e.getMessage());
        } catch (Exception e) {
            log.error("导入数据处理异常：", e);
            // 检查是否是ExcelValidationException
            if (e instanceof ExcelValidationException excelvalidationexception) {
                // 直接抛出Excel校验异常，不再包装
                throw excelvalidationexception;
            }
            
            // 检查异常链中是否包含ExcelValidationException
            Throwable cause = e.getCause();
            while (cause != null) {
                if (cause instanceof ExcelValidationException excelvalidationexception) {
                    // 直接抛出原始的校验异常，而不是包装它
                    throw excelvalidationexception;
                }
                cause = cause.getCause();
            }
            
            // 如果不是校验异常，则按原来方式处理
            throw new BusinessException("导入数据处理异常：" + e.getMessage());
        }
    }
    
    /**
     * 导出数据方法 - 标准HTTP响应方式
     * @param businessType 业务类型
     * @param params 导出参数
     * @param dynamicHeaders 动态表头
     * @param response HTTP响应对象
     */
    public void exportData(String businessType, Map<String, Object> params, 
                          Map<String, String> dynamicHeaders,
                           HttpServletResponse response) {
        // 设置响应头信息
        setResponseHeaders(response, businessType);
        
        // 使用通用导出方法，提供输出流创建函数
        exportDataInternal(businessType, params, dynamicHeaders, 
            () -> {
                try {
                    return response.getOutputStream();
                } catch (IOException e) {
                    log.error("创建响应输出流异常：", e);
                    throw new BusinessException("创建响应输出流异常：" + e.getMessage());
                }
            });
    }
    
    /**
     * 内部导出数据方法 - 统一处理导出逻辑
     * @param businessType 业务类型
     * @param params 导出参数
     * @param dynamicHeaders 动态表头
     * @param outputStreamSupplier 提供输出流的函数式接口
     */
    public void exportDataInternal(String businessType, Map<String, Object> params,
                                  Map<String, String> dynamicHeaders,
                                  OutputStreamSupplier outputStreamSupplier) {
        boolean permitAcquired = false;
        
        try {
            // 日志记录
            log.info("准备导出业务类型 [{}] 的数据", businessType);
            
            // 检查内存状态
            if (isMemoryInsufficient()) {
                throw new BusinessException("系统内存不足，请稍后再试");
            }
            
            // 尝试在5秒内获取许可
            permitAcquired = taskSemaphore.tryAcquire(5, TimeUnit.SECONDS);
            if (!permitAcquired) {
                throw new BusinessException("当前导出任务过多，请稍后再试");
            }
            
            // 增加任务计数
            taskCount.incrementAndGet();
            
            // 获取导出提供者
            ExportProvider<?> exportProvider = getExportProviderByType(businessType);
            if (exportProvider == null) {
                throw new BusinessException("未找到对应业务类型的导出服务: " + businessType);
            }

            // 开始导出处理
            processExcelExportInternal(exportProvider, params, dynamicHeaders, outputStreamSupplier);
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("获取导出许可被中断", e);
            throw new BusinessException("导出操作被中断");
        } catch (Exception e) {
            log.error("导出数据处理异常：", e);
            throw new BusinessException("导出数据处理异常：" + e.getMessage());
        } finally {
            // 任务完成，更新计数
            int remainingTasks = taskCount.decrementAndGet();
            log.info("导出任务完成，剩余任务数: {}", remainingTasks);
            
            // 释放许可
            if (permitAcquired) {
                taskSemaphore.release();
            }
        }
    }

    /**
     * 函数式接口 - 提供输出流
     */
    @FunctionalInterface
    public interface OutputStreamSupplier {
        OutputStream get() throws IOException;
    }
    
    /**
     * 设置HTTP响应头信息
     * @param response HTTP响应对象
     * @param businessType 业务类型
     */
    private void setResponseHeaders(HttpServletResponse response, String businessType) {
        try {
            // 设置文件名
            LocalDateTime now = LocalDateTime.now();
            String dateTime = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            String fileName = URLEncoder.encode(businessType + "_" + dateTime, StandardCharsets.UTF_8);
            
            // 修复文件名中的加号为空格，以便更好地兼容各浏览器
            fileName = fileName.replace("+", "%20");
            
            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            
            // 添加浏览器兼容处理
            response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s.xlsx\"; filename*=utf-8''%s.xlsx", fileName, fileName));
            
            // 缓存控制
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);
            
            // 添加CORS头部，允许前端在跨域请求中访问Content-Disposition头
            // 这对于前端正确获取文件名并触发下载是必需的
            // 标准的CORS安全策略默认不允许前端脚本读取此类响应头
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            
            log.info("导出文件名设置为: {}.xlsx", fileName);
        } catch (Exception e) {
            log.error("设置响应头异常：", e);
            throw new BusinessException("设置文件下载信息失败：" + e.getMessage());
        }
    }
    
    /**
     * 处理Excel导出 - 统一处理方法
     * @param exportProvider 导出提供者
     * @param params 导出参数
     * @param dynamicHeaders 动态表头
     * @param outputStreamSupplier 输出流提供者
     */
    private <T> void processExcelExportInternal(ExportProvider<T> exportProvider, 
                                      Map<String, Object> params,
                                      Map<String, String> dynamicHeaders, 
                                      OutputStreamSupplier outputStreamSupplier) {
        try {
            // 存储导出参数，供后续异步任务使用
            exportProvider.storeExportParams(params);
            
            // 检查是否指定了数据范围（多文件导出模式）
            boolean isRangeExport = params.containsKey(PARAM_START_RECORD) && params.containsKey(PARAM_END_RECORD);
            
            // 获取导出数据总量
            long totalCount;
            long startRecord = 0;
            long endRecord = 0;
            
            if (isRangeExport) {
                // 如果是范围导出，使用指定的范围
                startRecord = Long.parseLong(params.get(PARAM_START_RECORD).toString());
                endRecord = Long.parseLong(params.get(PARAM_END_RECORD).toString());
                totalCount = endRecord - startRecord;
                log.info("范围导出模式: 起始记录={}, 结束记录={}, 导出记录数={}", 
                        startRecord, endRecord, totalCount);
            } else {
                // 常规模式，获取全部数据总量
                totalCount = exportProvider.getExportDataCount(params);
            }
            
            try (ExcelWriter excelWriter = createExcelWriter(outputStreamSupplier.get())) {
                if (totalCount <= 0) {
                    handleEmptyDataExport(excelWriter, exportProvider, dynamicHeaders);
                    return;
                }
                
                // 计算分页参数
                int pageSize = DEFAULT_MAX_ROWS_PER_SHEET;
                int totalPages = (int) Math.ceil((double) totalCount / pageSize);
                log.info("导出数据总量: {}, 每页数量: {}, 总页数: {}", totalCount, pageSize, totalPages);
                
                // 异步获取所有页的数据
                List<CompletableFuture<List<T>>> dataFutures;
                
                if (isRangeExport) {
                    // 对于范围导出，使用特定范围的数据获取方法
                    dataFutures = fetchRangeDataAsync(exportProvider, params, pageSize, totalPages, 
                                                    startRecord, endRecord);
                } else {
                    // 常规导出，获取所有数据
                    dataFutures = fetchPageDataAsync(exportProvider, params, pageSize, totalPages);
                }
                
                // 依次写入各个sheet
                writeDataToSheets(excelWriter, exportProvider, dynamicHeaders, dataFutures);
                
                log.info("导出完成, 总数据量: {}, 总sheet数: {}", totalCount, totalPages);
            }
        } catch (Exception e) {
            log.error("导出Excel异常：", e);
            throw new BusinessException("导出Excel异常：" + e.getMessage());
        } finally {
            // 清理存储的参数
            exportProvider.clearExportParams();
        }
    }

    /**
     * 创建Excel写入器
     * @param outputStream 输出流对象
     * @return Excel写入器
     */
    private ExcelWriter createExcelWriter(OutputStream outputStream) {
        return EasyExcelFactory.write(outputStream)
                .registerConverter(new CustomBigDecimalConverter())
                .registerConverter(new CustomLocalDateConverter())
                .registerConverter(new CustomLocalDateTimeConverter())
                .registerConverter(new CustomDateConverter())
                .registerConverter(new CustomNumberConverter())
                .autoCloseStream(true)
                // 自动调整列宽
                .registerWriteHandler(new CustomWidthStyleStrategy())
                // 添加表头合并处理器
                .registerWriteHandler(new HorizontalCellMergeStrategy())
                // 添加单行表头策略
                .registerWriteHandler(new SingleRowHeaderStrategy())
                // 添加自定义单元格样式策略
                .registerWriteHandler(new CustomCellStyleStrategy())
                .build();
    }
    
    /**
     * 处理空数据导出
     * @param excelWriter Excel写入器
     * @param exportProvider 导出提供者
     * @param dynamicHeaders 动态表头
     */
    private <T> void handleEmptyDataExport(ExcelWriter excelWriter, 
                                        ExportProvider<T> exportProvider, 
                                        Map<String, String> dynamicHeaders) {
        log.info("导出数据为空，创建带表头的空文件");
        WriteSheet writeSheet = createWriteSheet(exportProvider, 1, dynamicHeaders);
        excelWriter.write(new ArrayList<>(), writeSheet);
    }
    
    /**
     * 异步获取分页数据
     * @param exportProvider 导出提供者
     * @param params 查询参数
     * @param pageSize 每页大小
     * @param totalPages 总页数
     * @return 异步任务列表
     */
    private <T> List<CompletableFuture<List<T>>> fetchPageDataAsync(
            ExportProvider<T> exportProvider,
            Map<String, Object> params,
            int pageSize,
            int totalPages) {
        
        List<CompletableFuture<List<T>>> futures = new ArrayList<>();
        
        log.info("开始异步获取所有数据, 总页数={}, 每页大小={}", totalPages, pageSize);
        
        try {
            // 创建信号量控制并发
            Semaphore pageSemaphore = new Semaphore(MAX_CONCURRENT_PAGES);
            
            // 复制参数，避免修改原参数
            Map<String, Object> exportParams = new HashMap<>(params);
            
            // 为每页创建一个异步任务
            for (int pageIndex = 0; pageIndex < totalPages; pageIndex++) {
                final int currentPageNum = pageIndex + 1;
                
                log.debug("创建页 {}/{} 的异步任务", currentPageNum, totalPages);
                
                // 为当前页创建分页参数
                Map<String, Object> pageParams = new HashMap<>(exportParams);
                pageParams.put("pageNum", currentPageNum);
                pageParams.put("pageSize", pageSize);
                
                // 创建异步任务
                CompletableFuture<List<T>> future = CompletableFuture.supplyAsync(() -> {
                    try {
                        // 获取信号量许可
                        pageSemaphore.acquire();
                        
                        // 记录内存使用情况
                        if (currentPageNum % 10 == 1) {
                            log.info("加载第 {} 页前, 内存使用率: {}", currentPageNum, 
                                   String.format(PERCENT_FORMAT, getMemoryUsagePercentage()));
                        }
                        
                        log.debug("开始加载页 {}/{}", currentPageNum, totalPages);
                        
                        // 获取此页数据
                        List<T> pageData = exportProvider.getExportData(pageParams, currentPageNum, pageSize);
                        
                        if (pageData == null) {
                            log.warn("页 {} 返回 null，使用空列表替代", currentPageNum);
                            pageData = new ArrayList<>();
                        }
                        
                        log.debug("页 {} 加载完成，获取到 {} 条记录", currentPageNum, pageData.size());
                        
                        return pageData;
                    } catch (InterruptedException e) {
                        // 正确处理中断异常，恢复中断状态
                        Thread.currentThread().interrupt();
                        log.error("页面 {} 加载被中断", currentPageNum);
                        throw new CompletionException(e);
                    } catch (Exception e) {
                        log.error("加载页 {} 数据异常: {}", currentPageNum, e.getMessage(), e);
                        throw new CompletionException(e);
                    } finally {
                        // 释放信号量
                        pageSemaphore.release();
                    }
                }, exportThreadPool);
                
                futures.add(future);
            }
            
            log.info("已创建 {} 个异步数据加载任务", futures.size());
        } catch (Exception e) {
            log.error("创建异步数据加载任务异常: {}", e.getMessage(), e);
            throw new BusinessException("创建数据加载任务失败: " + e.getMessage());
        }
        
        return futures;
    }
    
    /**
     * 将数据写入各个Sheet
     * @param excelWriter Excel写入器
     * @param exportProvider 导出提供者
     * @param dynamicHeaders 动态表头
     * @param dataFutures 异步数据任务列表
     */
    private <T> void writeDataToSheets(
            ExcelWriter excelWriter,
            ExportProvider<T> exportProvider,
            Map<String, String> dynamicHeaders,
            List<CompletableFuture<List<T>>> dataFutures) {
        
        final int totalSheets = dataFutures.size();
        final Map<String, Object> exportParams = exportProvider.getExportParams();
        
        log.info("开始处理总计{}个sheet的数据", totalSheets);
        
        // 创建进度追踪器
        final ExportProgressTracker progressTracker = new ExportProgressTracker(totalSheets);
        
        // 每个sheet页的处理计时，用于诊断性能问题
        final long[] sheetProcessTimes = new long[totalSheets];
        
        // 对第二个sheet采用特殊处理
        boolean secondSheetSpecialHandled = false;
        
        // 创建sheet处理上下文
        SheetProcessContext<T> context = new SheetProcessContext.Builder<T>()
                .excelWriter(excelWriter)
                .exportProvider(exportProvider)
                .dynamicHeaders(dynamicHeaders)
                .dataFutures(dataFutures)
                .exportParams(exportParams)
                .progressTracker(progressTracker)
                .sheetProcessTimes(sheetProcessTimes)
                .totalSheets(totalSheets)
                .build();
        
        // 预先加载几个页的数据后，通过滑动窗口方式加载后续数据
        for (int currentSheetIndex = 0; currentSheetIndex < totalSheets; currentSheetIndex++) {
            context.setCurrentSheetIndex(currentSheetIndex);
            context.setSecondSheetSpecialHandled(secondSheetSpecialHandled);
            
            processSheetWithErrorHandling(context);
            
            // 如果当前处理的是第二个sheet，标记为已特殊处理
            if (currentSheetIndex == 1) {
                secondSheetSpecialHandled = true;
            }
        }
        
        // 输出所有sheet处理的性能统计
        logSheetProcessingStats(sheetProcessTimes);
        
        log.info("所有{}个sheet数据写入完成，总耗时: {}ms", 
                totalSheets, progressTracker.getTotalProcessingTime());
    }
    
    /**
     * 多表格导入功能 - 将Excel中不同的sheet导入到不同的表中
     * 高性能线程池优化版本 - 使用并行处理提高导入速度
     * 支持事务管理，可以在所有sheet内容保存时使用同一个事务
     *
     * @param businessTypes 业务类型列表
     * @param file 导入文件
     * @param enableTransaction 是否启用事务管理
     */
    public void importMultiSheetExcel(List<String> businessTypes, MultipartFile file, boolean enableTransaction) {
        validateInputParameters(businessTypes);

        final long startTime = System.currentTimeMillis();
        logImportStart(businessTypes, file, enableTransaction);

        // 读取文件到内存
        final byte[] fileBytes = readFileBytes(file);
        
        try {
            // 1. 准备阶段 - 配置所有ReadSheet
            List<String> validationErrors = new ArrayList<>();
            List<ReadSheet> readSheets = prepareAndValidateSheets(businessTypes, validationErrors);
            
            // 验证准备阶段结果
            validatePrepareResult(validationErrors, readSheets);

            // 2. 处理阶段 - 根据是否启用事务选择不同的处理方式
            final long readStartTime = System.currentTimeMillis();
            log.info("开始读取Excel数据，准备阶段耗时: {}ms", readStartTime - startTime);
            
            // 处理Excel数据
            processExcelData(fileBytes, readSheets, enableTransaction);

            // 3. 总结阶段 - 计算耗时并输出日志
            logImportSummary(startTime, readStartTime, readSheets.size(), validationErrors);
        } catch (Exception e) {
            handleImportException(e);
        }
    }
    
    /**
     * 验证输入参数
     * 
     * @param businessTypes 业务类型列表
     * @throws IllegalArgumentException 如果业务类型列表为空
     */
    private void validateInputParameters(List<String> businessTypes) {
        if (businessTypes == null || businessTypes.isEmpty()) {
            throw new IllegalArgumentException("业务类型列表不能为空");
        }
    }
    
    /**
     * 记录导入开始日志
     * 
     * @param businessTypes 业务类型列表
     * @param file 导入文件
     * @param enableTransaction 是否启用事务
     */
    private void logImportStart(List<String> businessTypes, MultipartFile file, boolean enableTransaction) {
        log.info("开始多表格{}导入，共 {} 个业务类型，文件名: {}, 文件大小: {} bytes",
                enableTransaction ? "事务" : "并行", businessTypes.size(), file.getOriginalFilename(), file.getSize());
    }
    
    /**
     * 验证准备阶段结果
     * 
     * @param validationErrors 校验错误列表
     * @param readSheets 读取配置列表
     * @throws ExcelValidationException 如果存在校验错误
     * @throws BusinessException 如果没有找到可用的Sheet配置
     */
    private void validatePrepareResult(List<String> validationErrors, List<ReadSheet> readSheets) {
        if (!validationErrors.isEmpty()) {
            String errorMessage = String.join("\n", validationErrors);
            log.error("Excel校验失败: {}", errorMessage);
            throw new ExcelValidationException(-1, errorMessage, "多Sheet校验", -1);
        }
        
        if (readSheets.isEmpty()) {
            throw new BusinessException("没有找到可用的Sheet配置，请检查业务类型配置");
        }
    }
    
    /**
     * 处理Excel数据
     * 
     * @param fileBytes 文件字节数组
     * @param readSheets 读取配置列表
     * @param enableTransaction 是否启用事务
     */
    private void processExcelData(byte[] fileBytes, List<ReadSheet> readSheets, boolean enableTransaction) {
        if (enableTransaction) {
            // 使用事务处理所有sheet - 通过专用服务避免自调用问题
            if (excelTransactionService != null) {
                excelTransactionService.processInTransaction(fileBytes, readSheets);
            } else {
                log.warn("事务服务未配置，将使用非事务模式处理");
                processNonTransactionalSheets(fileBytes, readSheets);
            }
        } else {
            // 使用非事务处理模式
            processNonTransactionalSheets(fileBytes, readSheets);
        }
    }
    
    /**
     * 处理导入异常，包装为业务异常
     */
    private void handleImportException(Exception e) {
        // ExceptionUtils.handleImportException now directly throws the exception
        // so we don't need to do anything here - just pass through
        ExceptionUtils.handleImportException(e);
    }
    
    /**
     * 准备和验证所有的ReadSheet配置
     * 
     * @param businessTypes 业务类型列表
     * @param errors 错误收集列表
     * @return 准备好的ReadSheet列表
     */
    private List<ReadSheet> prepareAndValidateSheets(List<String> businessTypes, List<String> errors) {
        final List<ReadSheet> readSheets = Collections.synchronizedList(new ArrayList<>(businessTypes.size()));
        final long prepareStartTime = System.currentTimeMillis();
        
        // 并行准备所有ReadSheet
        List<CompletableFuture<ReadSheet>> prepareTasks = new ArrayList<>(businessTypes.size());

        for (int i = 0; i < businessTypes.size(); i++) {
            final int sheetIndex = i;
            final String businessType = businessTypes.get(i);

            // 每个Sheet的处理任务提交到线程池
            CompletableFuture<ReadSheet> task = CompletableFuture.supplyAsync(() -> 
                prepareAndValidateSheet(sheetIndex, businessType, errors), executor);

            prepareTasks.add(task);
        }

        // 等待所有准备任务完成
        try {
            // 设置较短的超时时间，因为这只是配置阶段
            List<ReadSheet> validSheets = prepareTasks.stream()
                .map(future -> {
                    try {
                        return future.get(5, TimeUnit.SECONDS);
                    } catch (InterruptedException e) {
                        // 设置中断标志
                        Thread.currentThread().interrupt();
                        log.error("准备Sheet配置被中断", e);
                        errors.add("Sheet配置被中断: " + e.getMessage());
                        return null;
                    } catch (Exception e) {
                        log.error("准备Sheet配置异常", e);
                        errors.add("Sheet配置异常: " + e.getMessage());
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .toList();
            
            readSheets.addAll(validSheets);
            
            log.info("所有Sheet配置并行准备完成，共 {} 个，耗时: {}ms",
                    readSheets.size(), System.currentTimeMillis() - prepareStartTime);
        } catch (Exception e) {
            log.error("Sheet配置准备阶段发生异常", e);
            errors.add("导入准备失败: " + e.getMessage());
            
            // 检查异常链中是否包含InterruptedException
            Throwable cause = e;
            while (cause != null) {
                if (cause instanceof InterruptedException) {
                    Thread.currentThread().interrupt();
                    break;
                }
                cause = cause.getCause();
            }
        }
        
        // 按Sheet索引排序，确保处理顺序正确
        readSheets.sort(Comparator.comparingInt(ReadSheet::getSheetNo));
        return readSheets;
    }
    
    /**
     * 准备并验证单个Sheet的配置
     *
     * @param sheetIndex sheet索引
     * @param businessType 业务类型
     * @param errors 错误信息收集列表
     * @return ReadSheet配置，如果配置失败则返回null
     */
    private ReadSheet prepareAndValidateSheet(int sheetIndex, String businessType, List<String> errors) {
        try {
            log.debug("线程 [{}] 准备业务类型 [{}] 的Sheet配置", Thread.currentThread().getName(), businessType);

            // 1. 获取监听器
            ReadListener<?> listener = getListenerByType(businessType);
            if (listener == null) {
                errors.add(String.format("未找到业务类型 [%s] 对应的监听器", businessType));
                return null;
            }

            // 2. 获取实体类型
            Class<?> entityClass = getEntityClassSafely(listener, businessType, errors);
            if (entityClass == null) {
                return null;
            }

            // 3. 创建ReadSheet配置
            return EasyExcelFactory.readSheet(sheetIndex)
                    .head(entityClass)
                    .registerConverter(new CustomBigDecimalConverter())
                    .registerConverter(new CustomLocalDateConverter())
                    .registerConverter(new CustomLocalDateTimeConverter())
                    .registerConverter(new CustomDateConverter())
                    .registerConverter(new CustomNumberConverter())
                    .registerReadListener(listener)
                    .build();
        } catch (Exception e) {
            log.error("准备业务类型 [{}] 的配置时出错: {}", businessType, e.getMessage());
            errors.add(String.format("业务类型 [%s] 配置错误: %s", businessType, e.getMessage()));
            return null;
        }
    }
    
    /**
     * 读取文件到字节数组
     * 
     * @param file 上传的文件
     * @return 文件字节数组
     */
    private byte[] readFileBytes(MultipartFile file) {
        try {
            return file.getBytes();
        } catch (IOException e) {
            log.error("读取文件数据到内存时发生异常", e);
            throw new BusinessException("读取文件数据到内存时发生异常: " + e.getMessage());
        }
    }
    
    /**
     * 处理所有配置好的Sheet（非事务模式）
     * 每个sheet独立处理，一个sheet失败不影响其他sheet
     * 
     * @param fileBytes 文件字节数组
     * @param readSheets 待处理的Sheet列表
     */
    private void processNonTransactionalSheets(byte[] fileBytes, List<ReadSheet> readSheets) {
        // 记录处理失败的sheet及其错误信息
        Map<Integer, String> failedSheets = new HashMap<>();
        // 记录原始异常，用于保留详细错误信息
        Map<Integer, Throwable> originalExceptions = new HashMap<>();
        
        // 记录总sheet数
        int totalSheets = readSheets.size();
        log.info("开始非事务模式处理所有sheet，共 {} 个", totalSheets);
        
        // 使用处理策略处理所有sheet
        processSheetsByStrategy(fileBytes, readSheets, failedSheets, originalExceptions);
        
        // 报告失败结果但不中断处理
        if (!failedSheets.isEmpty()) {
            int failedSheetCount = failedSheets.size();
            int successSheetCount = totalSheets - failedSheetCount;
            
            // 构建错误信息
            String errorMessage = String.format("共%d个sheet, %d个成功, %d个失败。失败原因为: %s", 
                totalSheets, successSheetCount, failedSheetCount, formatFailedSheetsMessages(failedSheets));
            
            log.error("部分sheet导入失败: {}", errorMessage);
            
            // 在非事务模式下，我们仍然需要抛出一个异常表示有失败的sheet
            // 但此时其他成功的sheet已经处理完毕，不会回滚
            throw new BusinessException(errorMessage);
        } else {
            log.info("所有 {} 个sheet处理成功", totalSheets);
        }
    }
    
    /**
     * 格式化失败sheet的错误信息
     * 
     * @param failedSheets 失败的sheet信息映射
     * @return 格式化后的错误信息
     */
    private String formatFailedSheetsMessages(Map<Integer, String> failedSheets) {
        StringBuilder messageBuilder = new StringBuilder();
        failedSheets.forEach((sheetNo, errorMsg) -> messageBuilder.append(errorMsg).append("; "));
        
        String message = messageBuilder.toString().trim();
        // 去掉最后一个分号（如果存在）
        if (message.endsWith(";")) {
            message = message.substring(0, message.length() - 1);
        }
        return message;
    }
    
    /**
     * 处理少量Sheet（4个或更少）- 每个使用独立的ExcelReader
     * 确保一个sheet的错误不会影响到其他sheet的处理
     * 
     * @param fileBytes 文件字节数组
     * @param readSheets 待处理的Sheet列表
     * @param failedSheets 记录失败Sheet的Map
     * @param originalExceptions 记录原始异常的Map
     */
    private void processSheetsByIndividualReaders(byte[] fileBytes, List<ReadSheet> readSheets, 
                                          Map<Integer, String> failedSheets, 
                                          Map<Integer, Throwable> originalExceptions) {
        // 逐个处理sheet，每个sheet使用独立的ExcelReader
        for (ReadSheet sheet : readSheets) {
            int sheetNo = sheet.getSheetNo() + 1;
            String sheetName = sheet.getSheetName() != null ? sheet.getSheetName() : SHEET_PREFIX + sheetNo;
            log.info("处理{}[{}:{}]", SHEET_PREFIX, sheetNo, sheetName);
            
            // 如果此sheet需要跳过（之前已完成或已手动标记为失败），则不处理
            if (failedSheets.containsKey(sheetNo)) {
                log.info("跳过已标记为失败的Sheet[{}:{}]", sheetNo, sheetName);
                continue;
            }
            
            // 为每个Sheet创建独立的ExcelReader
            try (ExcelReader sheetReader = createExcelReader(fileBytes)) {
                processSheetWithReader(sheetReader, sheet, sheetNo, sheetName, failedSheets, originalExceptions);
            } catch (Exception e) {
                // 如果创建ExcelReader也失败，记录错误但继续处理其他sheet
                log.error("为Sheet[{}:{}]创建ExcelReader失败: {}", sheetNo, sheetName, e.getMessage(), e);
                
                // 记录sheet创建读取器失败
                failedSheets.put(sheetNo, String.format("Sheet[%d:%s] 创建处理器失败: %s", 
                                                     sheetNo, sheetName, e.getMessage()));
                originalExceptions.put(sheetNo, e);
            }
        }
    }

    /**
     * 使用给定的ExcelReader处理单个Sheet
     * 
     * @param sheetReader Excel读取器
     * @param sheet 要处理的ReadSheet
     * @param sheetNo Sheet编号
     * @param sheetName Sheet名称
     * @param failedSheets 记录失败Sheet的Map
     * @param originalExceptions 记录原始异常的Map
     */
    private void processSheetWithReader(ExcelReader sheetReader, ReadSheet sheet, int sheetNo, String sheetName,
                                  Map<Integer, String> failedSheets, Map<Integer, Throwable> originalExceptions) {
        try {
            // 处理单个sheet
            sheetReader.read(Collections.singletonList(sheet));
            log.info("{}[{}:{}]处理成功", SHEET_PREFIX, sheetNo, sheetName);
        } catch (Exception e) {
            // 捕获并记录异常，继续处理下一个sheet
            log.error("处理Sheet[{}:{}]失败: {}", sheetNo, sheetName, e.getMessage(), e);
            
            // 记录失败信息，但继续处理其他sheet
            ExceptionUtils.handleSheetException(e, sheetNo, sheetName, failedSheets, originalExceptions);
        }
    }
    
    /**
     * 创建Excel读取器
     *
     * @param fileBytes 文件字节数组
     * @return Excel读取器实例
     */
    private ExcelReader createExcelReader(byte[] fileBytes) {
        return EasyExcelFactory.read(new ByteArrayInputStream(fileBytes))
                .registerConverter(new CustomBigDecimalConverter())
                .registerConverter(new CustomLocalDateConverter())
                .registerConverter(new CustomLocalDateTimeConverter())
                .registerConverter(new CustomDateConverter())
                .registerConverter(new CustomNumberConverter())
                .build();
    }
    
    /**
     * 根据sheet数量选择不同的处理策略
     *
     * @param fileBytes 文件字节数组
     * @param readSheets Sheet列表
     * @param failedSheets 记录失败Sheet的Map
     * @param originalExceptions 记录原始异常的Map
     */
    private void processSheetsByStrategy(byte[] fileBytes, List<ReadSheet> readSheets, 
                                      Map<Integer, String> failedSheets, 
                                      Map<Integer, Throwable> originalExceptions) {
        if (readSheets.size() <= 4) {
            // 如果sheet数量少，逐个处理
            processSheetsByIndividualReaders(fileBytes, readSheets, failedSheets, originalExceptions);
        } else {
            // 如果sheet数量多，分批并行处理
            processManySheets(fileBytes, readSheets, failedSheets, originalExceptions);
        }
    }
    
    /**
     * 处理大量Sheet（超过4个）
     * 
     * @param fileBytes 文件字节数组
     * @param readSheets Sheet列表
     * @param failedSheets 记录失败Sheet的Map
     * @param originalExceptions 记录原始异常的Map
     */
    private void processManySheets(byte[] fileBytes, List<ReadSheet> readSheets, 
                                 Map<Integer, String> failedSheets,
                                 Map<Integer, Throwable> originalExceptions) {
        // 按照最佳分组大小划分sheet
        int optimalBatchSize = calculateOptimalBatchSize(readSheets.size());
        List<List<ReadSheet>> sheetBatches = splitIntoBatches(readSheets, optimalBatchSize);
        
        log.info("将{}个sheet分为{}个批次并行处理，每批次{}个sheet", 
               readSheets.size(), sheetBatches.size(), optimalBatchSize);
        
        List<CompletableFuture<Void>> readTasks = new ArrayList<>(sheetBatches.size());
        
        // 记录每个批次任务的错误信息
        ConcurrentHashMap<Integer, String> batchErrors = new ConcurrentHashMap<>();
        
        for (int batchIndex = 0; batchIndex < sheetBatches.size(); batchIndex++) {
            final int currentBatchIndex = batchIndex;
            final List<ReadSheet> batch = sheetBatches.get(batchIndex);
            
            CompletableFuture<Void> readTask = CompletableFuture.runAsync(() -> {
                try {
                    processBatchWithErrorHandling(fileBytes, batch, failedSheets, originalExceptions);
                } catch (Exception e) {
                    log.error("批次{}处理发生异常: {}", currentBatchIndex, e.getMessage(), e);
                    batchErrors.put(currentBatchIndex, "批次处理异常: " + e.getMessage());
                }
            }, executor);
            
            readTasks.add(readTask);
        }
        
        // 等待所有读取任务完成
        try {
            CompletableFuture.allOf(readTasks.toArray(new CompletableFuture[0])).get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("数据读取阶段被中断", e);
            throw new BusinessException("数据导入失败: 操作被中断");
        } catch (Exception e) {
            log.error("数据读取阶段发生异常", e);
            throw new BusinessException("数据导入失败: " + e.getMessage());
        }
        
        // 如果有批次错误，记录到失败sheet中
        if (!batchErrors.isEmpty()) {
            batchErrors.forEach((batchIndex, errorMsg) -> 
                log.error("批次{}处理失败: {}", batchIndex, errorMsg)
            );
        }
    }
    
    /**
     * 处理一批Sheet，包含单独的错误处理
     * 
     * @param fileBytes 文件字节数组
     * @param batch Sheet批次
     * @param failedSheets 记录失败Sheet的Map
     * @param originalExceptions 记录原始异常的Map
     */
    private void processBatchWithErrorHandling(byte[] fileBytes, List<ReadSheet> batch, 
                                            Map<Integer, String> failedSheets,
                                            Map<Integer, Throwable> originalExceptions) {
        // 记录批次信息用于日志
        int firstSheetNo = batch.get(0).getSheetNo();
        int lastSheetNo = batch.get(batch.size() - 1).getSheetNo();
        log.debug("线程 [{}] 开始处理Sheet批次 {}-{}",
                Thread.currentThread().getName(), firstSheetNo, lastSheetNo);
        
        // 逐个处理batch中的sheet，每个sheet使用独立的ExcelReader，确保单个sheet失败不影响其他sheet
        for (ReadSheet sheet : batch) {
            int sheetNo = sheet.getSheetNo() + 1;
            String sheetName = sheet.getSheetName() != null ? sheet.getSheetName() : SHEET_PREFIX + sheetNo;
            
            // 如果此sheet需要跳过（之前已完成或已手动标记为失败），则不处理
            if (failedSheets.containsKey(sheetNo)) {
                log.info("跳过已标记为失败的Sheet[{}:{}]", sheetNo, sheetName);
                continue;
            }
            
            // 为每个sheet创建独立的ExcelReader
            try (ExcelReader sheetReader = createExcelReader(fileBytes)) {
                processSheetWithReader(sheetReader, sheet, sheetNo, sheetName, failedSheets, originalExceptions);
            } catch (Exception e) {
                // 如果创建ExcelReader也失败，记录错误但继续处理其他sheet
                log.error("为Sheet[{}:{}]创建ExcelReader失败: {}", sheetNo, sheetName, e.getMessage(), e);
                
                // 记录sheet创建读取器失败
                failedSheets.put(sheetNo, String.format("Sheet[%d:%s] 创建处理器失败: %s", 
                                                     sheetNo, sheetName, e.getMessage()));
                originalExceptions.put(sheetNo, e);
            }
        }
        
        log.debug("Sheet批次 {}-{} 处理完成", firstSheetNo, lastSheetNo);
    }
    
    /**
     * 记录导入过程的总结信息
     * 
     * @param startTime 开始时间
     * @param readStartTime 读取开始时间
     * @param sheetCount 处理的Sheet数量
     * @param errors 错误列表
     */
    private void logImportSummary(long startTime, long readStartTime, int sheetCount, List<String> errors) {
        final long endTime = System.currentTimeMillis();
        final long totalTime = endTime - startTime;
        final long prepareTime = readStartTime - startTime;
        final long readTime = endTime - readStartTime;
        
        log.info("多表格并行导入完成，共处理 {} 个Sheet，总耗时: {}ms (准备: {}ms, 读取: {}ms)",
                sheetCount, totalTime, prepareTime, readTime);
        
        if (!errors.isEmpty()) {
            log.warn("导入过程有以下警告: {}", errors);
        }
    }

    /**
     * Sheet处理上下文
     */
    @Getter
    private static class SheetProcessContext<T> {
        private final ExcelWriter excelWriter;
        private final ExportProvider<T> exportProvider;
        private final Map<String, String> dynamicHeaders;
        private final List<CompletableFuture<List<T>>> dataFutures;
        private final Map<String, Object> exportParams;
        private final ExportProgressTracker progressTracker;
        private final long[] sheetProcessTimes;
        private final int totalSheets;
        @Setter
        private int currentSheetIndex;
        @Setter
        private boolean secondSheetSpecialHandled;
        
        private SheetProcessContext(Builder<T> builder) {
            this.excelWriter = builder.excelWriter;
            this.exportProvider = builder.exportProvider;
            this.dynamicHeaders = builder.dynamicHeaders;
            this.dataFutures = builder.dataFutures;
            this.exportParams = builder.exportParams;
            this.progressTracker = builder.progressTracker;
            this.sheetProcessTimes = builder.sheetProcessTimes;
            this.totalSheets = builder.totalSheets;
        }

        /**
         * Builder for SheetProcessContext
         */
        public static class Builder<T> {
            private ExcelWriter excelWriter;
            private ExportProvider<T> exportProvider;
            private Map<String, String> dynamicHeaders;
            private List<CompletableFuture<List<T>>> dataFutures;
            private Map<String, Object> exportParams;
            private ExportProgressTracker progressTracker;
            private long[] sheetProcessTimes;
            private int totalSheets;
            
            public Builder<T> excelWriter(ExcelWriter excelWriter) {
                this.excelWriter = excelWriter;
                return this;
            }
            
            public Builder<T> exportProvider(ExportProvider<T> exportProvider) {
                this.exportProvider = exportProvider;
                return this;
            }
            
            public Builder<T> dynamicHeaders(Map<String, String> dynamicHeaders) {
                this.dynamicHeaders = dynamicHeaders;
                return this;
            }
            
            public Builder<T> dataFutures(List<CompletableFuture<List<T>>> dataFutures) {
                this.dataFutures = dataFutures;
                return this;
            }
            
            public Builder<T> exportParams(Map<String, Object> exportParams) {
                this.exportParams = exportParams;
                return this;
            }
            
            public Builder<T> progressTracker(ExportProgressTracker progressTracker) {
                this.progressTracker = progressTracker;
                return this;
            }
            
            public Builder<T> sheetProcessTimes(long[] sheetProcessTimes) {
                this.sheetProcessTimes = sheetProcessTimes;
                return this;
            }
            
            public Builder<T> totalSheets(int totalSheets) {
                this.totalSheets = totalSheets;
                return this;
            }
            
            public SheetProcessContext<T> build() {
                return new SheetProcessContext<>(this);
            }
        }
    }
    
    /**
     * 处理单个Sheet，包含错误处理
     */
    private <T> void processSheetWithErrorHandling(SheetProcessContext<T> context) {
        final long startTime = System.currentTimeMillis();
        final int sheetIndex = context.getCurrentSheetIndex();
        
        try {
            // 处理单个sheet
            processSheet(context, startTime);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new BusinessException("导出操作被中断");
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("处理第{}个sheet时发生异常: {}", sheetIndex + 1, e.getMessage(), e);
            // 继续处理下一个sheet而不是完全失败
        }
    }
    
    /**
     * 处理单个Sheet
     */
    private <T> void processSheet(SheetProcessContext<T> context, long startTime) throws Exception {
        final int sheetIndex = context.getCurrentSheetIndex();
            
        // 检查是否是第二个sheet (index=1)
        if (sheetIndex == 1) {
            handleSecondSheet(context, startTime);
            return; // 特殊处理完第2个sheet后，直接处理下一个
        }
        
        log.info("开始处理第{}个sheet，当前进度: {}%", 
                sheetIndex + 1, context.getProgressTracker().getProgressPercentage());
        
        // 清理资源
        cleanupResourcesForSheet(context);
        
        // 加载并写入数据
        loadAndWriteSheetData(context);
        
        // 完成处理
        finalizeSheetProcessing(context, startTime);
    }
    
    /**
     * 处理第二个sheet并更新状态
     */
    private <T> void handleSecondSheet(SheetProcessContext<T> context, long startTime) {
        final int sheetIndex = context.getCurrentSheetIndex();
            
        log.info("检测到第2个sheet，将采用特殊处理方式，防止卡死");
        handleSecondSheetSpecially(
                context.getExcelWriter(), 
                context.getExportProvider(), 
                context.getDynamicHeaders(), 
                context.getExportParams(), 
                sheetIndex);
                
        context.getSheetProcessTimes()[sheetIndex] = System.currentTimeMillis() - startTime;
        context.getProgressTracker().markSheetCompleted(sheetIndex);
    }
    
    /**
     * 为当前Sheet清理资源
     */
    private <T> void cleanupResourcesForSheet(SheetProcessContext<T> context) throws InterruptedException {
        final int currentIndex = context.getCurrentSheetIndex();
        final List<CompletableFuture<List<T>>> dataFutures = context.getDataFutures();
        final boolean secondSheetSpecialHandled = context.isSecondSheetSpecialHandled();
            
        if (currentIndex <= 0) {
            return;
        }
        
        // 强制清理前面所有sheet的数据
        for (int i = 0; i < currentIndex; i++) {
            if (i != 1 || secondSheetSpecialHandled) { // 不清除第2个sheet的数据，除非已特殊处理
                dataFutures.set(i, null);
            }
        }
        
        // 主动触发GC以释放内存
        log.info("释放内存资源");
        TimeUnit.MICROSECONDS.sleep(300); // 给GC一点时间
        
        // 如果内存不足或压力大，等待更长时间
        if (isMemoryPressureHigh()) {
            log.warn("当前内存压力较大，暂停1秒后继续");
            TimeUnit.SECONDS.sleep(1);
            TimeUnit.MICROSECONDS.sleep(300); // 给GC一点时间
        }
    }
    
    /**
     * 加载并写入Sheet数据
     */
    private <T> void loadAndWriteSheetData(SheetProcessContext<T> context) {
        final int sheetIndex = context.getCurrentSheetIndex();
        final ExcelWriter excelWriter = context.getExcelWriter();
        final ExportProvider<T> exportProvider = context.getExportProvider();
        final Map<String, String> dynamicHeaders = context.getDynamicHeaders();
        final List<CompletableFuture<List<T>>> dataFutures = context.getDataFutures();
        final Map<String, Object> exportParams = context.getExportParams();
            
        try {
            // 加载数据
            List<T> data = loadSheetData(exportProvider, dataFutures, exportParams, sheetIndex);
            if (data == null) {
                // 创建空sheet
                createEmptySheet(excelWriter, exportProvider, dynamicHeaders, sheetIndex);
                return;
            }
            
            // 写入数据
            writeSheetDataToExcel(excelWriter, exportProvider, dynamicHeaders, data, sheetIndex);
        } catch (Exception e) {
            log.error("加载或写入第{}个sheet数据异常: {}", sheetIndex + 1, e.getMessage(), e);
            createEmptySheet(excelWriter, exportProvider, dynamicHeaders, sheetIndex);
        }
    }
    
    /**
     * 完成Sheet处理
     */
    private <T> void finalizeSheetProcessing(SheetProcessContext<T> context, long startTime) throws InterruptedException {
        final int sheetIndex = context.getCurrentSheetIndex();
        final List<CompletableFuture<List<T>>> dataFutures = context.getDataFutures();
        final ExportProgressTracker progressTracker = context.getProgressTracker();
        final long[] sheetProcessTimes = context.getSheetProcessTimes();
            
        // 清理当前sheet数据
        dataFutures.set(sheetIndex, null);
        
        // 检查内存
        checkMemoryPeriodically(sheetIndex);
        
        // 记录处理时间
        sheetProcessTimes[sheetIndex] = System.currentTimeMillis() - startTime;
        log.info("完成第{}个sheet处理，耗时: {}ms，内存使用率: {}%", 
                sheetIndex + 1, 
                sheetProcessTimes[sheetIndex],
                getMemoryUsagePercentage());
        
        // 更新进度
        progressTracker.markSheetCompleted(sheetIndex);
        
        // 每个sheet处理完成后强制休息一下
        TimeUnit.MICROSECONDS.sleep(300);
        
        // 第一个sheet后额外等待
        if (sheetIndex == 0) {
            TimeUnit.MICROSECONDS.sleep(500); // 给系统一点时间
        }
    }
    
    /**
     * 特殊处理第二个sheet，避免卡死
     */
    private <T> void handleSecondSheetSpecially(
            ExcelWriter excelWriter,
            ExportProvider<T> exportProvider,
            Map<String, String> dynamicHeaders,
            Map<String, Object> exportParams,
            int sheetIndex) {
            
            final int sheetNo = sheetIndex + 1;
            try {
                log.info("使用特殊策略处理第{}个sheet，直接从数据源获取并分段写入", sheetNo);
                
                // 0. 先创建sheet
                WriteSheet writeSheet = createWriteSheet(exportProvider, sheetNo, dynamicHeaders);
                
                // 1. 使用较小的批次直接获取数据
                Map<String, Object> pageParams = new HashMap<>(exportParams);
                pageParams.put(PARAM_SHEET_NO, sheetNo);
                
                // 使用更小的pageSize，减少单次数据量
                final int maxRows = 8000; // 限制为8000行
                List<T> data = exportProvider.getExportData(pageParams, sheetNo, maxRows);
                
                if (data == null || data.isEmpty()) {
                    log.info("第{}个sheet数据为空，仅写入表头", sheetNo);
                    excelWriter.write(new ArrayList<>(), writeSheet);
                    return;
                }
                
                log.info("第{}个sheet获取到数据，行数: {}", sheetNo, data.size());
                
                // 2. 使用超小批次写入
                final int microBatchSize = 100; // 每批次仅100行
                int batches = (int) Math.ceil((double) data.size() / microBatchSize);
                
                for (int i = 0; i < batches; i++) {
                    int start = i * microBatchSize;
                    int end = Math.min(start + microBatchSize, data.size());
                    
                    log.debug("写入第{}个sheet的第{}批次数据, {}行 ({}/{})", 
                            sheetNo, i+1, (end-start), end, data.size());
                    
                    // 创建新的列表，避免引用原始大列表
                    List<T> batchData = new ArrayList<>(data.subList(start, end));
                    
                    // 使用同步方式写入
                    excelWriter.write(batchData, writeSheet);
                    
                    // 立即清理
                    batchData.clear();
                    
                    // 每5批次休息一下，避免写入过快
                    if (i > 0 && i % 5 == 0) {
                        log.debug("批次{}写入后暂停50ms", i);
                        TimeUnit.MILLISECONDS.sleep(50);
                    }
                }
                
                // 3. 强制清理内存
                data.clear();
                
                log.info("第{}个sheet特殊处理完成", sheetNo);
                
            } catch (InterruptedException e) {
                // 确保中断状态被正确传播
                Thread.currentThread().interrupt();
                log.error("第{}个sheet特殊处理被中断: {}", sheetNo, e.getMessage());
                throw new BusinessException("导出处理被中断");
            } catch (Exception e) {
                log.error("第{}个sheet特殊处理失败: {}", sheetNo, e.getMessage(), e);
                try {
                    // 如果失败，写入空表头
                    WriteSheet writeSheet = createWriteSheet(exportProvider, sheetNo, dynamicHeaders);
                    excelWriter.write(new ArrayList<>(), writeSheet);
                } catch (Exception ex) {
                    log.error("创建空表头也失败", ex);
                }
            }
        }
    
    /**
     * 分段加载单个sheet的数据，优化内存使用
     * 适用于大数据量sheet，特别是从第3个sheet开始
     */
    private <T> List<T> streamLoadSheetData(int sheetIndex, ExportProvider<T> exportProvider, Map<String, Object> params) 
            throws InterruptedException, ExecutionException {
        
        int pageNum = sheetIndex + 1;
        log.info("使用流式加载方式获取第{}个sheet数据", pageNum);
        
        try {
            // 直接从数据源获取数据，避免中间缓存
            Map<String, Object> pageParams = new HashMap<>(params);
            pageParams.put(PARAM_SHEET_NO, pageNum);
            
            // 使用较小的pageSize，减少单次内存占用
            List<T> data = exportProvider.getExportData(pageParams, pageNum, DEFAULT_MAX_ROWS_PER_SHEET);
            
            if (data != null) {
                log.info("成功加载第{}个sheet数据，共{}条记录", pageNum, data.size());
            } else {
                log.warn("第{}个sheet数据加载为null", pageNum);
                data = new ArrayList<>();
            }
            
            return data;
        } catch (Exception e) {
            // 检查是否是中断异常
            log.error("流式加载第{}个sheet数据异常: {}", pageNum, e.getMessage(), e);
            throw new CompletionException(e);
        }
    }
    
    /**
     * 流式写入Sheet数据，使用更小的批次
     * @throws BusinessException 如果写入过程中发生异常
     */
    private <T> void streamWriteSheetData(
            ExcelWriter excelWriter,
            WriteSheet writeSheet,
            List<T> pageData) {
        
        final int dataSize = pageData.size();
        final int batchSize = BATCH_WRITE_SIZE;
        
        if (dataSize <= batchSize) {
            excelWriter.write(pageData, writeSheet);
            return;
        }
        
        // 计算批次
        int batchCount = (int) Math.ceil((double) dataSize / batchSize);
        log.info("数据量较大({}行)，分{}批流式写入", dataSize, batchCount);
        
        // 使用较小的批次直接写入，避免并行处理的开销
        for (int batchIndex = 0; batchIndex < batchCount; batchIndex++) {
            int startIdx = batchIndex * batchSize;
            int endIdx = Math.min(startIdx + batchSize, dataSize);
            
            processBatchWrite(excelWriter, writeSheet, pageData, batchIndex, batchCount, startIdx, endIdx);
        }
        
        log.info("流式写入完成，总数据量: {}", dataSize);
    }

    /**
     * 处理批量写入Excel的单个批次
     * @param excelWriter Excel写入器
     * @param writeSheet 写入的Sheet
     * @param pageData 页面数据
     * @param batchIndex 当前批次索引
     * @param batchCount 总批次数
     * @param startIdx 起始索引
     * @param endIdx 结束索引
     * @throws BusinessException 如果写入过程中发生异常
     */
    private <T> void processBatchWrite(
            ExcelWriter excelWriter,
            WriteSheet writeSheet,
            List<T> pageData,
            int batchIndex,
            int batchCount,
            int startIdx,
            int endIdx) {
    
        try {
            // 创建独立副本，避免持有大列表引用
            List<T> batchData = new ArrayList<>(pageData.subList(startIdx, endIdx));
            
            // 直接写入Excel
            excelWriter.write(batchData, writeSheet);
            
            // 立即清理
            batchData.clear();
            
            // 定期检查内存
            if (batchIndex % 10 == 0) {
                double memoryUsage = getMemoryUsagePercentage();
                log.debug("批次{}/{}完成，内存使用率：{}%", 
                        batchIndex+1, batchCount, String.format("%.1f", memoryUsage));
                
                if (memoryUsage > 80) {
                    checkMemoryAndPause(memoryUsage);
                }
            }
        } catch (Exception e) {
            log.error("批处理写入异常(批次{}/{}): {}", batchIndex + 1, batchCount, e.getMessage(), e);
            throw new BusinessException("数据写入异常: " + e.getMessage());
        }
    }

    /**
     * 检查内存使用率并在内存使用率高时暂停
     * @param memoryUsage 当前内存使用率百分比
     * @throws BusinessException 如果线程被中断，抛出业务异常
     */
    private void checkMemoryAndPause(double memoryUsage) {
        log.warn("批处理内存使用率较高({}%)，暂停100毫秒", String.format("%.1f", memoryUsage));
        try {
            TimeUnit.MILLISECONDS.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("批处理休眠被中断: {}", e.getMessage());
            throw new BusinessException("数据写入被中断");
        }
    }
    
    /**
     * 获取当前内存使用百分比
     */
    private double getMemoryUsagePercentage() {
        MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
        long maxMemory = heapMemoryUsage.getMax();
        long usedMemory = heapMemoryUsage.getUsed();
        return (double) usedMemory * 100 / maxMemory;
    }

    /**
     * 导出进度追踪类，用于监控导出过程
     */
    private static class ExportProgressTracker {
        private final int totalSheets;
        private final AtomicInteger completedSheets = new AtomicInteger(0);
        private final long startTime = System.currentTimeMillis();
        private final boolean[] completionStatus;
        
        public ExportProgressTracker(int totalSheets) {
            this.totalSheets = totalSheets;
            this.completionStatus = new boolean[totalSheets];
        }
        
        public void markSheetCompleted(int sheetIndex) {
            if (sheetIndex >= 0 && sheetIndex < totalSheets && !completionStatus[sheetIndex]) {
                completionStatus[sheetIndex] = true;
                completedSheets.incrementAndGet();
            }
        }
        
        public int getProgressPercentage() {
            if (totalSheets == 0) return 100;
            return completedSheets.get() * 100 / totalSheets;
        }
        
        public long getTotalProcessingTime() {
            return System.currentTimeMillis() - startTime;
        }
    }
    
    /**
     * 记录sheet处理的性能统计
     */
    private void logSheetProcessingStats(long[] processingTimes) {
        if (processingTimes == null || processingTimes.length == 0) {
            return;
        }
        
        long totalTime = 0;
        long maxTime = 0;
        int maxTimeSheet = 0;
        
        StringBuilder timesLog = new StringBuilder("Sheet处理时间统计(ms): ");
        
        for (int i = 0; i < processingTimes.length; i++) {
            if (processingTimes[i] > 0) {
                timesLog.append(SHEET_PREFIX).append(i + 1).append("=").append(processingTimes[i]).append(", ");
                totalTime += processingTimes[i];
                
                if (processingTimes[i] > maxTime) {
                    maxTime = processingTimes[i];
                    maxTimeSheet = i + 1;
                }
            }
        }
        
        log.info(timesLog.toString());
        log.info("Sheet处理总耗时: {}ms, 平均每个Sheet: {}ms, 最慢的是Sheet{}: {}ms", 
                totalTime, 
                totalTime / processingTimes.length,
                maxTimeSheet,
                maxTime);
    }
    
    /**
     * 判断当前内存压力是否较高
     * @return 如果内存使用率超过85%，返回true
     */
    private boolean isMemoryPressureHigh() {
        MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
        long maxMemory = heapMemoryUsage.getMax();
        long usedMemory = heapMemoryUsage.getUsed();
        double usedRatio = (double) usedMemory / maxMemory;
        
        return usedRatio > 0.85;
    }
    
    /**
     * 触发单个页面的数据加载
     * @param sheetIndex sheet索引
     * @param dataFutures 异步数据任务列表
     * @param exportProvider 导出提供者
     * @param exportParams 导出参数
     */
    private <T> void triggerSinglePageLoading(
            int sheetIndex,
            List<CompletableFuture<List<T>>> dataFutures,
            ExportProvider<T> exportProvider,
            Map<String, Object> exportParams) {
        
        // 如果该页已经触发了加载，则跳过
        if (dataFutures.get(sheetIndex) != null) {
            return;
        }
        
        // 创建异步任务加载该页数据
        CompletableFuture<List<T>> future = CompletableFuture.supplyAsync(() -> {
            try {
                log.info("正在异步加载第{}个sheet的数据", sheetIndex + 1);
                // 复制导出参数，避免并发修改
                Map<String, Object> pageParams = new HashMap<>(exportParams);
                // 设置当前页码
                int pageNum = sheetIndex + 1;
                pageParams.put(PARAM_SHEET_NO, pageNum);
                return exportProvider.getExportData(pageParams, pageNum, DEFAULT_MAX_ROWS_PER_SHEET);
            } catch (Exception e) {
                log.error("异步加载第{}个sheet数据失败: {}", sheetIndex + 1, e.getMessage(), e);
                throw new CompletionException(e);
            }
        }, executor);
        
        // 更新到任务列表中
        dataFutures.set(sheetIndex, future);
    }
    
    /**
     * 定期检查内存状况
     * @param currentIndex 当前处理的索引
     */
    private void checkMemoryPeriodically(int currentIndex) {
        // 每处理2个sheet检查一次内存，并判断内存是否不足
        if (currentIndex % 2 == 0) {
            // 获取当前内存使用情况
            MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
            long maxMemory = heapMemoryUsage.getMax();
            long usedMemory = heapMemoryUsage.getUsed();
            double usedRatio = (double) usedMemory / maxMemory;
            
            // 记录高内存使用率，但不主动触发GC
            if (usedRatio > 0.70) {
                log.warn("内存使用率较高: {}，建议减少单次导出数据量", String.format(PERCENT_FORMAT, usedRatio * 100));
            }
            
            // 检查是否内存不足
            if (isMemoryInsufficient()) {
                throw new BusinessException("导出过程中内存不足，请减少导出数据量或稍后再试");
            }
        }
    }
    
    /**
     * 创建Excel写入sheet
     * @param exportProvider 导出提供者
     * @param sheetNo sheet编号
     * @param dynamicHeaders 动态表头
     * @return WriteSheet对象
     */
    private <T> WriteSheet createWriteSheet(ExportProvider<T> exportProvider, 
                                         int sheetNo, 
                                         Map<String, String> dynamicHeaders) {
        // 获取Excel表单名称
        String sheetName = exportProvider.getSheetName() + sheetNo;
        
        // 创建WriteSheet构建器
        ExcelWriterSheetBuilder sheetBuilder = EasyExcelFactory.writerSheet(sheetNo - 1, sheetName);

        if (dynamicHeaders != null && !dynamicHeaders.isEmpty()) {
            // 提取字段名列表，用于includeColumnFieldNames
            List<String> fieldNames = new ArrayList<>(dynamicHeaders.keySet());
            
            if (isComplexHeader(dynamicHeaders)) {
                // 复杂表头处理 - 多行显示
                List<List<String>> complexHeaders = parseComplexHeaders(dynamicHeaders);
                sheetBuilder.head(complexHeaders)
                          .includeColumnFieldNames(fieldNames); // 设置要包含的字段
                
                log.info("使用复杂动态表头导出sheet [{}], 表头层数: {}, 字段数量: {}", 
                        sheetName, 
                        complexHeaders.isEmpty() ? 0 : complexHeaders.get(0).size(),
                        fieldNames.size());
            } else {
                // 简单表头处理 - 单行显示
                // 创建正确的表头结构：每列一个List，每个List中只有一个元素
                List<List<String>> columnHeaders = new ArrayList<>();
                
                // 遍历每个字段及其表头名称
                for (Map.Entry<String, String> entry : dynamicHeaders.entrySet()) {
                    // 为每一列创建一个单独的List
                    List<String> columnHeader = new ArrayList<>();
                    columnHeader.add(entry.getValue());
                    
                    // 添加到总表头结构
                    columnHeaders.add(columnHeader);
                }
                
                // 设置表头和字段
                sheetBuilder.head(columnHeaders)
                          .includeColumnFieldNames(fieldNames);
                
                log.info("使用简单动态表头导出sheet [{}], 列数: {}, 字段: {}", 
                        sheetName, columnHeaders.size(), fieldNames);
            }
        } else {
            // 使用实体类注解作为表头
            sheetBuilder.head(exportProvider.getEntityClass());
            log.info("使用实体类注解导出sheet [{}], 实体类: {}", 
                    sheetName, exportProvider.getEntityClass().getSimpleName());
        }
        
        return sheetBuilder.build();
    }
    
    /**
     * 判断是否为复杂表头
     * 复杂表头格式示例: {"field1":"表头1", "field2":"父表头.子表头1", "field3":"父表头.子表头2"}
     */
    private boolean isComplexHeader(Map<String, String> dynamicHeaders) {
        for (String headerValue : dynamicHeaders.values()) {
            if (headerValue.contains(".")) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 解析复杂表头结构
     * 将带有层级关系的表头转换为EasyExcel需要的复杂表头格式
     * 例如：要实现如下表头
     * |  发票信息（跨2列）  |
     * | 发票编号 | 发票金额 |
     * 输入：{"invoiceId":"发票信息.发票编号", "invoiceAmount":"发票信息.发票金额"}
     * 正确的结构应该是：
     * [
     *   ["发票信息", "发票编号"], // 第一列：第一行是"发票信息"，第二行是"发票编号"
     *   ["发票信息", "发票金额"]  // 第二列：第一行是"发票信息"，第二行是"发票金额"
     * ]
     */
    private List<List<String>> parseComplexHeaders(Map<String, String> dynamicHeaders) {
        List<List<String>> result = new ArrayList<>();
        
        // 1. 计算最大层级数
        int maxLevel = 1;
        for (String headerValue : dynamicHeaders.values()) {
            int levels = headerValue.split("\\.").length;
            maxLevel = Math.max(maxLevel, levels);
        }
        
        // 2. 按列构建表头
        for (String headerText : dynamicHeaders.values()) {
            String[] levels = headerText.split("\\.");
            
            // 创建这一列的表头
            List<String> columnHeader = new ArrayList<>();
            
            // 添加每个层级表头
            for (int i = 0; i < maxLevel; i++) {
                if (i < levels.length) {
                    columnHeader.add(levels[i]);
                } else {
                    columnHeader.add("");
                }
            }
            
            // 添加到结果中
            result.add(columnHeader);
        }
        
        log.info("复杂表头结构（列数: {}，行数: {}）: {}", 
                result.size(), result.isEmpty() ? 0 : result.get(0).size(), result);
        
        return result;
    }
    
    /**
     * 获取实体类型
     * @param listener 监听器
     * @return 实体类
     */
    public Class<?> getEntityClass(ReadListener<?> listener) {
        try {
            // 尝试不同的策略获取实体类型
            Class<?> entityClass = getEntityClassFromGenericInterface(listener);
            if (entityClass != null) {
                return entityClass;
            }
            
            entityClass = getEntityClassFromGenericSuperclass(listener);
            if (entityClass != null) {
                return entityClass;
            }
            
            entityClass = getEntityClassFromInvokeMethod(listener);
            if (entityClass != null) {
                return entityClass;
            }
            
            entityClass = getEntityClassFromClassField(listener);
            if (entityClass != null) {
                return entityClass;
            }
            
            throw new IllegalArgumentException("无法确定监听器的泛型类型");
        } catch (Exception e) {
            log.error("获取实体类型失败", e);
            throw new IllegalArgumentException("获取实体类型失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 从泛型接口中获取实体类型
     */
    private Class<?> getEntityClassFromGenericInterface(ReadListener<?> listener) {
        for (Type genericInterface : listener.getClass().getGenericInterfaces()) {
            if (genericInterface instanceof ParameterizedType parameterizedType) {
                Type rawType = parameterizedType.getRawType();
                if (rawType instanceof Class && 
                        ReadListener.class.isAssignableFrom((Class<?>) rawType)) {
                    Type[] typeArguments = parameterizedType.getActualTypeArguments();
                    if (typeArguments.length > 0 && typeArguments[0] instanceof Class) {
                        log.debug("从接口泛型获取到实体类: {}", typeArguments[0]);
                        return (Class<?>) typeArguments[0];
                    }
                }
            }
        }
        return null;
    }
    
    /**
     * 从泛型父类中获取实体类型
     */
    private Class<?> getEntityClassFromGenericSuperclass(ReadListener<?> listener) {
        Type genericSuperclass = listener.getClass().getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType parameterizedType) {
            Type[] typeArguments = parameterizedType.getActualTypeArguments();
            if (typeArguments.length > 0 && typeArguments[0] instanceof Class) {
                log.debug("从父类泛型获取到实体类: {}", typeArguments[0]);
                return (Class<?>) typeArguments[0];
            }
        }
        return null;
    }
    
    /**
     * 从invoke方法参数中获取实体类型
     */
    private Class<?> getEntityClassFromInvokeMethod(ReadListener<?> listener) {
        for (java.lang.reflect.Method method : listener.getClass().getDeclaredMethods()) {
            if (method.getName().equals("invoke")) {
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length > 0 && !parameterTypes[0].equals(Object.class)) {
                    log.debug("从invoke方法参数获取到实体类: {}", parameterTypes[0]);
                    return parameterTypes[0];
                }
            }
        }
        return null;
    }
    
    /**
     * 从类字段中获取实体类型
     */
    private Class<?> getEntityClassFromClassField(ReadListener<?> listener) throws IllegalAccessException {
        for (java.lang.reflect.Field field : listener.getClass().getDeclaredFields()) {
            if (field.getType().equals(Class.class)) {
                try {
                    String getterName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                    java.lang.reflect.Method getter = listener.getClass().getMethod(getterName);
                    Object value = getter.invoke(listener);
                    if (value instanceof Class) {
                        log.debug("从字段getter获取到实体类: {}", value);
                        return (Class<?>) value;
                    }
                } catch (NoSuchMethodException | SecurityException | IllegalArgumentException | java.lang.reflect.InvocationTargetException e) {
                    log.trace("无法通过getter获取字段 {}: {}", field.getName(), e.getMessage());
                    throw new IllegalArgumentException("无法通过getter获取字段 " + field.getName() + ": " + e.getMessage(), e);
                }
            }
        }
        return null;
    }
    
    /**
     * 检查是否内存不足
     * 当可用内存低于安全阈值（{@link #MEMORY_SAFETY_THRESHOLD}）时返回true
     * @return 如果内存不足返回true，否则返回false
     */
    private boolean isMemoryInsufficient() {
        MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
        long maxMemory = heapMemoryUsage.getMax();
        long usedMemory = heapMemoryUsage.getUsed();
        
        // 计算可用内存比例
        double availableRatio = (double)(maxMemory - usedMemory) / maxMemory;
        
        if (availableRatio < MEMORY_SAFETY_THRESHOLD) {
            log.warn("系统可用内存不足，当前可用内存比例: " + String.format(PERCENT_FORMAT, availableRatio * 100));
            return true;
        }
        return false;
    }
    
    /**
     * 资源清理
     */
    @PreDestroy
    public void cleanup() {
        log.info("执行EasyExcelUtil资源清理...");
        
        // 等待所有导入导出任务完成
        if (taskCount.get() > 0) {
            log.info("等待{}个未完成的任务...", taskCount.get());
            
            try {
                // 等待已有任务完成，但最多等待30秒
                long deadline = System.currentTimeMillis() + 30000;
                while (taskCount.get() > 0 && System.currentTimeMillis() < deadline) {
                    TimeUnit.MILLISECONDS.sleep(500);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.warn("等待任务完成被中断");
            }
        }
        
        log.info("EasyExcelUtil资源清理完成");
    }

    /**
     * 创建空表头sheet
     */
    private <T> void createEmptySheet(
            ExcelWriter excelWriter,
            ExportProvider<T> exportProvider,
            Map<String, String> dynamicHeaders,
            int sheetIndex) {
            
        try {
            WriteSheet writeSheet = createWriteSheet(exportProvider, sheetIndex + 1, dynamicHeaders);
            excelWriter.write(new ArrayList<>(), writeSheet);
            log.info("为第{}个sheet创建空表头", sheetIndex + 1);
        } catch (Exception e) {
            log.error("创建空表头失败", e);
        }
    }
    
    /**
     * 加载第一个sheet数据
     */
    private <T> List<T> loadFirstSheetData(
            int sheetIndex,
            ExportProvider<T> exportProvider,
            Map<String, Object> exportParams,
            List<CompletableFuture<List<T>>> dataFutures) throws Exception {
            
        CompletableFuture<List<T>> future = dataFutures.get(sheetIndex);
        if (future == null) {
            log.info("第{}个sheet数据未加载，触发加载", sheetIndex + 1);
            triggerSinglePageLoading(sheetIndex, dataFutures, exportProvider, exportParams);
            future = dataFutures.get(sheetIndex);
        }
        
        return future.get(5, TimeUnit.MINUTES);
    }

    /**
     * 加载Sheet数据
     */
    private <T> List<T> loadSheetData(
            ExportProvider<T> exportProvider,
            List<CompletableFuture<List<T>>> dataFutures,
            Map<String, Object> exportParams,
            int sheetIndex) throws Exception {
            
        if (sheetIndex == 0) {
            // 第一个sheet用预加载方式
            return loadFirstSheetData(sheetIndex, exportProvider, exportParams, dataFutures);
        } else {
            // 其他sheet直接加载
            return streamLoadSheetData(sheetIndex, exportProvider, exportParams);
        }
    }
    
    /**
     * 写入Sheet数据到Excel
     */
    private <T> void writeSheetDataToExcel(
            ExcelWriter excelWriter,
            ExportProvider<T> exportProvider,
            Map<String, String> dynamicHeaders,
            List<T> data,
            int sheetIndex) {
            
        int sheetNo = sheetIndex + 1;
        WriteSheet writeSheet = createWriteSheet(exportProvider, sheetNo, dynamicHeaders);
        
        if (data != null && !data.isEmpty()) {
            log.info("第{}个sheet: 写入{}行数据", sheetNo, data.size());
            streamWriteSheetData(excelWriter, writeSheet, data);
        } else {
            log.info("第{}个sheet: 数据为空，仅写入表头", sheetNo);
            excelWriter.write(new ArrayList<>(), writeSheet);
        }
    }

    /**
     * 计算最佳批处理大小
     * @param totalSize 总数量
     * @return 最佳批次大小
     */
    private int calculateOptimalBatchSize(int totalSize) {
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        // 确保至少2个处理器可用，避免过度并行
        int effectiveProcessors = Math.max(2, availableProcessors - 1);
        // 根据处理器数量和总数据量计算批次大小
        return Math.max(1, (int)Math.ceil((double)totalSize / effectiveProcessors));
    }

    /**
     * 将列表分割成多个批次
     * @param items 需要分割的列表
     * @param batchSize 每个批次的大小
     * @return 分割后的批次列表
     */
    private <T> List<List<T>> splitIntoBatches(List<T> items, int batchSize) {
        List<List<T>> batches = new ArrayList<>();
        for (int i = 0; i < items.size(); i += batchSize) {
            int endIndex = Math.min(i + batchSize, items.size());
            batches.add(new ArrayList<>(items.subList(i, endIndex)));
        }
        return batches;
    }

    /**
     * 获取指定业务类型的导出提供者
     * 
     * @param businessType 业务类型
     * @return 导出提供者，如果未找到则返回null
     */
    public <T> ExportProvider<T> getExportProvider(String businessType) {
        if (businessType == null || businessType.trim().isEmpty()) {
            return null;
        }
        
        // 直接从缓存获取
        @SuppressWarnings("unchecked")
        ExportProvider<T> provider = (ExportProvider<T>) exportProviderMap.get(businessType);
        return provider;
    }

    /**
     * 异步获取指定范围的数据（用于多文件导出）
     * @param exportProvider 导出提供者
     * @param params 查询参数
     * @param pageSize 每页大小
     * @param totalPages 总页数
     * @param startRecord 起始记录索引（从0开始）
     * @param endRecord 结束记录索引（不包含）
     * @return 异步任务列表
     */
    private <T> List<CompletableFuture<List<T>>> fetchRangeDataAsync(
            ExportProvider<T> exportProvider,
            Map<String, Object> params,
            int pageSize,
            int totalPages,
            long startRecord,
            long endRecord) {
        
        List<CompletableFuture<List<T>>> futures = new ArrayList<>();
        
        log.info("开始异步获取范围数据: 起始={}, 结束={}, 总页数={}", startRecord, endRecord, totalPages);
        
        try {
            // 创建信号量控制并发
            Semaphore pageSemaphore = new Semaphore(MAX_CONCURRENT_PAGES);
            
            // 复制参数，避免修改原参数
            Map<String, Object> exportParams = new HashMap<>(params);
            
            // 为每页创建一个异步任务
            for (int pageIndex = 0; pageIndex < totalPages; pageIndex++) {
                final int currentPageNum = pageIndex + 1;
                // 修复整数乘法隐式转换为long的问题，确保使用long进行计算
                final long pageOffset = (long)pageIndex * (long)pageSize;
                final long pageStart = startRecord + pageOffset;
                final long pageEnd = Math.min(pageStart + pageSize, endRecord);
                
                // 实际页大小可能小于 pageSize（尤其是最后一页）
                final int actualPageSize = (int)(pageEnd - pageStart);
                
                if (actualPageSize <= 0) {
                    log.warn("页 {} 的实际大小 <= 0，跳过", currentPageNum);
                    futures.add(CompletableFuture.completedFuture(new ArrayList<>()));
                    continue;
                }
                
                log.debug("创建页 {}/{} 的异步任务, 范围: {}-{}, 记录数: {}", 
                         currentPageNum, totalPages, pageStart, pageEnd, actualPageSize);
                
                // 为当前页创建分页参数
                Map<String, Object> pageParams = new HashMap<>(exportParams);
                pageParams.put("pageNum", currentPageNum);
                pageParams.put("pageSize", actualPageSize);
                pageParams.put("rangeStart", pageStart);
                pageParams.put("rangeEnd", pageEnd);
                
                // 创建异步任务
                CompletableFuture<List<T>> future = CompletableFuture.supplyAsync(() -> {
                    try {
                        // 获取信号量许可
                        pageSemaphore.acquire();
                        
                        log.debug("开始加载页 {}/{}, 范围: {}-{}", 
                                 currentPageNum, totalPages, pageStart, pageEnd);
                        
                        // 获取此页数据
                        List<T> pageData = exportProvider.getExportData(pageParams, currentPageNum, actualPageSize);
                        
                        if (pageData == null) {
                            log.warn("页 {} 返回 null，使用空列表替代", currentPageNum);
                            pageData = new ArrayList<>();
                        } else {
                            log.debug("页 {} 加载完成，获取到 {} 条记录", currentPageNum, pageData.size());
                        }
                        
                        return pageData;
                    } catch (InterruptedException e) {
                        // 正确处理中断异常，恢复中断状态
                        Thread.currentThread().interrupt();
                        log.error("页面 {} 加载被中断", currentPageNum);
                        throw new CompletionException(e);
                    } catch (Exception e) {
                        log.error("加载页 {} 数据异常: {}", currentPageNum, e.getMessage(), e);
                        throw new CompletionException(e);
                    } finally {
                        // 释放信号量
                        pageSemaphore.release();
                    }
                }, exportThreadPool);
                
                futures.add(future);
            }
            
            log.info("已创建 {} 个异步数据加载任务", futures.size());
        } catch (Exception e) {
            log.error("创建异步数据加载任务异常: {}", e.getMessage(), e);
            throw new BusinessException("创建数据加载任务失败: " + e.getMessage());
        }
        
        return futures;
    }


    /**
     * 事务上下文，用于在多个监听器之间共享状态
     */
    @Setter
    @Getter
    public static class TransactionContext {
        private boolean failed = false;
        private String errorMessage;

    }

    /**
     * 安全地获取实体类型，并处理可能的异常
     * 
     * @param listener 监听器
     * @param businessType 业务类型，用于错误信息
     * @param errors 错误收集列表
     * @return 实体类类型，获取失败时返回null
     */
    private Class<?> getEntityClassSafely(ReadListener<?> listener, String businessType, List<String> errors) {
        try {
            return getEntityClass(listener);
        } catch (Exception e) {
            errors.add(String.format("无法获取业务类型 [%s] 的实体类型: %s", businessType, e.getMessage()));
            return null;
        }
    }

}
